﻿namespace DCHealthCheck {

    #region Usings
    using Contoso.ActiveDirectory;
    using DCHealthCheck.DomainModel;
    using System;
    using System.Collections.Generic;
    using System.DirectoryServices.ActiveDirectory;
    using System.Linq;
    using System.Text; 
    #endregion

    public class ReplicationNeighborBuilder {

        #region Members
        private readonly System.DirectoryServices.ActiveDirectory.ReplicationNeighbor ADReplicationNeighbor;

        private readonly DCHealthCheck.DomainModel.ReplicationNeighbor ReplicationNeighbor;

        private readonly SiteServer SiteServer; 
        #endregion

        #region Constructors
        private ReplicationNeighborBuilder() {
        }

        public ReplicationNeighborBuilder(
            DCHealthCheck.DomainModel.ReplicationNeighbor replicationNeighbor,
            System.DirectoryServices.ActiveDirectory.ReplicationNeighbor adReplicationNeighbor,
            SiteServer siteServer)
            : this() {
            if (replicationNeighbor == null) {
                throw new ArgumentNullException("replicationNeighbor");
            }
            if (adReplicationNeighbor == null) {
                throw new ArgumentNullException("adReplicationNeighbor");
            }

            this.ReplicationNeighbor = replicationNeighbor;
            this.ADReplicationNeighbor = adReplicationNeighbor;
            this.SiteServer = siteServer;
        } 
        #endregion

        #region Methods
        public DCHealthCheck.DomainModel.ReplicationNeighbor GetReplicationNeighbor() {
            this.ReplicationNeighbor.ConsecutiveFailureCount = this.ADReplicationNeighbor.ConsecutiveFailureCount;
            this.ReplicationNeighbor.SourceServer = this.ADReplicationNeighbor.SourceServer;
            this.ReplicationNeighbor.LastAttemptedSyncUTC = this.ADReplicationNeighbor.LastAttemptedSync;
            this.ReplicationNeighbor.LastSuccessfulSyncUTC = this.ADReplicationNeighbor.LastSuccessfulSync;
            this.ReplicationNeighbor.LastSyncMessage = this.ADReplicationNeighbor.LastSyncMessage.Replace(Environment.NewLine, string.Empty);
            this.ReplicationNeighbor.LastSyncResult = this.ADReplicationNeighbor.LastSyncResult;
            this.ReplicationNeighbor.PartitionName = this.ADReplicationNeighbor.PartitionName;
            this.ReplicationNeighbor.ReplicationNeighborOption = this.ADReplicationNeighbor.ReplicationNeighborOption.ToString();
            this.ReplicationNeighbor.SourceInvocationId = this.ADReplicationNeighbor.SourceInvocationId;
            this.ReplicationNeighbor.USNAttributeFilter = this.ADReplicationNeighbor.UsnAttributeFilter;
            this.ReplicationNeighbor.USNLastObjectChangeSynced = this.ADReplicationNeighbor.UsnLastObjectChangeSynced;

            #region Get replication reason

            if ((this.SiteServer != null) && (this.ReplicationNeighbor.SourceServer.IndexOf(".") > 0)) {
                string sourceServerShortName = this.ReplicationNeighbor.SourceServer.Substring(0, this.ReplicationNeighbor.SourceServer.IndexOf(".")).ToLower();

                var ntdsConnection =
                this.SiteServer.NTDSSettings.NTDSConnections
                    .Where(x => 
                        x.FromServer.ToLower().Contains(sourceServerShortName) &&
                        x.PartitionList.Any(y => string.Equals(y.Key, this.ReplicationNeighbor.PartitionName, StringComparison.OrdinalIgnoreCase)))
                    .FirstOrDefault();

                if (ntdsConnection != null) {
                    if (ntdsConnection.PartitionList.ContainsKey(this.ReplicationNeighbor.PartitionName)) {
                        this.ReplicationNeighbor.ReplicationReason = ntdsConnection.PartitionList[this.ReplicationNeighbor.PartitionName].ToString();
                    }
                    else {
                        //Log.WarnFormat("[ThreadID: {0}] {1} Server: {2} NTDSConnection parition object not found for neighbor server: {3} partition: {4}",
                        //    Thread.CurrentThread.ManagedThreadId, Utility.CurrentMethodName(),systemInfo.ComputerAccountProperties.DnsHostName,
                        //    replicationNeighbor.SourceServer, replicationNeighbor.PartitionName);
                    }
                }
                else {
                    //Log.WarnFormat("[ThreadID: {0}] {1} Server: {2} NTDSConnection object not found for neighbor server: {3} partition: {4}",
                    //    Thread.CurrentThread.ManagedThreadId, Utility.CurrentMethodName(),systemInfo.ComputerAccountProperties.DnsHostName, replicationNeighbor.SourceServer, replicationNeighbor.PartitionName);
                }
            } // if ((this.siteServer != null) && (this.replicationNeighbor.SourceServer.IndexOf(".") > 0))
            #endregion

            return this.ReplicationNeighbor;
        }

        public override string ToString() {
            if (this.ReplicationNeighbor != null) {
                return this.ReplicationNeighbor.ToString();
            }
            else {
                return string.Empty;
            }
        } 
        #endregion
    }
}
